// functional/Closure7.java
// (c)2017 MindView LLC: see Copyright.txt
// We make no guarantees that this code is fit for any purpose.
// Visit http://OnJava8.com for more book information.
// {WillNotCompile}

import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.IntSupplier;

public class Closure7 {
//    IntSupplier makeFun(int x) {
//        Integer i = 0;
//        i = i + 1;
//        return () -> x + i;
//    }

    /*
    根据你提供的Closure7.java文件内容，问题出在lambda表达式中引用了局部变量i，而i在方法中被修改了（通过i = i + 1）。这违反了Java中lambda表达式的规则：lambda表达式只能引用final或实际上是final的局部变量。
    详细分析
    x是方法参数，它是实际上的final，因为方法参数在方法体内不能被重新赋值。
    i是一个局部变量，并且在方法体中被重新赋值（i = i + 1），因此它不再是final或实际上是final，导致lambda表达式无法引用它。
     */

  //解决方案
    /*
    使用数组来存储可变值
    可以将i存储在一个数组中，这样可以间接地修改它的值
    */
  IntSupplier makeFun1(int x) {
    Integer[] i = {0}; // 使用数组来存储可变值
    i[0] = i[0] + 1; // 修改数组中的值
    return () -> x + i[0];
  }

  /*
  使用AtomicInteger
  AtomicInteger是一个线程安全的类，可以用来存储和修改整数值。
  */
  IntSupplier makeFun2(int x) {
    AtomicInteger i = new AtomicInteger(0); // 使用AtomicInteger
    i.incrementAndGet(); // 修改AtomicInteger中的值
    return () -> x + i.get();
  }

  /*
  提前计算并赋值给一个不可变变量
  如果不需要在lambda表达式中动态修改i，可以在返回lambda之前计算好结果并赋值给一个新的不可变变量。
  */
  IntSupplier makeFun3(int x) {
    Integer i = 0;
    int finalI = i + 1; // 提前计算并赋值给一个不可变变量
    return () -> x + finalI;
  }

  public static void main(String[] args) {
    Closure7 closure7 = new Closure7();
    IntSupplier supplier1 = closure7.makeFun1(5);
    System.out.println(supplier1.getAsInt()); // 输出 6 (5+1)
    System.out.println();
    IntSupplier supplier2 = closure7.makeFun2(5);
    System.out.println(supplier2.getAsInt()); // 输出 6 (5+1)
    System.out.println();
    IntSupplier supplier3 = closure7.makeFun3(5);
    System.out.println(supplier3.getAsInt()); // 输出 6 (5+1)
  }

}
